package com.tianji.promotion.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.utils.CodeUtil;
import com.tianji.promotion.dto.CodeQuery;
import com.tianji.promotion.dto.ExchangeCodeStatus;
import com.tianji.promotion.entity.ExchangeCode;
import com.tianji.promotion.mapper.ExchangeCodeMapper;
import com.tianji.promotion.service.IExchangeCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.tianji.common.constants.RedisConstants.SERIAL_NO_KEY;

/**
 * <p>
 * 兑换码 服务实现类
 * </p>
 *
 * @author xjs
 */
@Service
public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, ExchangeCode> implements IExchangeCodeService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    @Async("threadPoolTaskExecutor")
    public void asyncGenerateExchageCode(int totalNum, Long couponId, LocalDateTime issueEndTime){
        // 序列号从多少开始？redis
        String key = SERIAL_NO_KEY;
        // 得到兑换码的序列号的最大值，当前redis中的序列号是100，现在想生成100个序列号，直接+100，maxNo=20
        // 访问一次redis，得到一批序列号
        int maxNo = redisTemplate.opsForValue().increment(key, totalNum).intValue();
        Collection<ExchangeCode> codeList = new ArrayList<>();
        for (int i = 0; i <totalNum; i++) {
            int no = maxNo - i;
            String code = CodeUtil.generateCode(no, couponId);
            ExchangeCode ex = new ExchangeCode();
            ex.setId(no);
            ex.setCode(code);
            ex.setStatus(1);
            ex.setExchangeTargetId(couponId);
            ex.setExpiredTime(issueEndTime);
            ex.setCreateTime(LocalDateTime.now());
            ex.setUpdateTime(LocalDateTime.now());
            codeList.add(ex);
        }
        // 分批写入数据库
        this.saveBatch(codeList, 100);
    }

    @Override
    public void deleteByCouponId(Long couponId) {
        LambdaQueryWrapper<ExchangeCode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExchangeCode::getExchangeTargetId, couponId);
        this.remove(wrapper);
    }

    @Override
    public PageDTO<ExchangeCode> pageQuery(CodeQuery query) {
        Page<ExchangeCode> ipage = query.toMpPageDefaultSortByCreateTimeDesc();
        LambdaQueryWrapper<ExchangeCode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(query.getCouponId() != null, ExchangeCode::getExchangeTargetId, query.getCouponId())
                .eq(query.getStatus() != null, ExchangeCode::getStatus, query.getStatus());
        IPage<ExchangeCode> page = this.page(ipage, wrapper);
        List<ExchangeCode> records = page.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return PageDTO.empty(ipage);
        }
        return PageDTO.of(ipage, records);
    }

    @Override
    public void updateExchangeCode(long id, Long userId, ExchangeCodeStatus used) {
        ExchangeCode exchangeCode = new ExchangeCode();
        exchangeCode.setId((int)id);
        exchangeCode.setUserId(userId);
        exchangeCode.setStatus(used.getValue());
        this.updateById(exchangeCode);
    }
}
